<template>
  <el-form
    v-show="getShow"
    ref="formLogin"
    :model="registeParam"
    :rules="registerRules"
    class="login-form"
    label-position="top"
    label-width="120px"
    size="large"
  >
    <el-row style="margin-right: -10px; margin-left: -10px">
      <el-col :span="24" style="padding-right: 10px; padding-left: 10px">
        <el-form-item>
          <LoginFormTitle style="width: 100%" />
        </el-form-item>
      </el-col>
      <el-col :span="24" style="padding-right: 10px; padding-left: 10px">
        <el-form-item prop="UserName">
          <el-input
            v-model="registeParam.UserName"
            :placeholder="t('login.usernamePlaceholder')"
            size="large"
            :prefix-icon="iconAvatar"
          />
        </el-form-item>
      </el-col>
      <el-col :span="24" style="padding-right: 10px; padding-left: 10px">
        <el-form-item prop="FullName">
          <el-input
            v-model="registeParam.FullName"
            :placeholder="t('login.fullnamePlaceholder')"
            size="large"
            :prefix-icon="iconAvatar"
          />
        </el-form-item>
      </el-col>
      <el-col :span="24" style="padding-right: 10px; padding-left: 10px">
        <el-form-item prop="RegisterTenant">
          <el-switch
            v-model="registerInitData.RegisterTenant"
            active-text="注册租户"
            inactive-text="系统用户"
            active-value="1"
            inactive-value="0"
            inline-prompt
            size="large"
            class="ml-1"
            style="

--el-switch-off-color: #13ce66"
          />
        </el-form-item>
      </el-col>
      <el-col
        :span="24"
        style="padding-right: 10px; padding-left: 10px"
        v-show="registerInitData.RegisterTenant == 1"
      >
        <el-form-item prop="TenantName">
          <el-input
            v-model="registeParam.TenantName"
            :placeholder="t('login.tenantname')"
            :prefix-icon="iconHouse"
            link
            type="primary"
            size="large"
          />
        </el-form-item>
      </el-col>
      <el-col
        :span="24"
        style="padding-right: 10px; padding-left: 10px"
        v-show="registerInitData.RegisterTenant == 1"
      >
        <el-form-item prop="TenantDomain">
          <el-input
            v-model="registeParam.TenantDomain"
            :placeholder="t('login.tenantdomain')"
            :prefix-icon="iconDomain"
            link
            type="primary"
            size="large"
          />
        </el-form-item>
      </el-col>
      <el-col :span="24" style="padding-right: 10px; padding-left: 10px">
        <el-form-item prop="Mobile">
          <el-input
            v-model="registeParam.Mobile"
            :placeholder="t('login.mobilePlaceholder')"
            size="large"
            :prefix-icon="iconPhone"
          />
        </el-form-item>
      </el-col>
      <el-col :span="24" style="padding-right: 10px; padding-left: 10px">
        <el-form-item prop="Email">
          <el-input
            v-model="registeParam.Email"
            :placeholder="t('login.emailPlaceholder')"
            size="large"
            :prefix-icon="iconEmail"
          />
        </el-form-item>
      </el-col>
      <el-col :span="24" style="padding-right: 10px; padding-left: 10px">
        <el-form-item prop="PassWord">
          <el-input
            v-model="registeParam.PassWord"
            type="PassWord"
            auto-complete="off"
            :placeholder="t('login.password')"
            size="large"
            :prefix-icon="iconLock"
            show-password
          />
        </el-form-item>
      </el-col>
      <el-col :span="24" style="padding-right: 10px; padding-left: 10px">
        <el-form-item prop="ConfirmPassword">
          <el-input
            v-model="registeParam.ConfirmPassword"
            type="password"
            size="large"
            auto-complete="off"
            :placeholder="t('login.checkPassword')"
            :prefix-icon="iconLock"
            show-password
          />
        </el-form-item>
      </el-col>
      <el-col :span="24" style="padding-right: 10px; padding-left: 10px">
        <el-form-item>
          <XButton
            :loading="loginLoading"
            :title="t('login.register')"
            class="w-[100%]"
            type="primary"
            @click="getCode"
          />
        </el-form-item>
      </el-col>
      <ClickCaptcha
        ref="clickCaptchaInstance"
        :config="captchaConf"
        :events="captchaEvents"
        :data="captchaData"
      />
    </el-row>
    <XButton :title="t('login.hasUser')" class="w-[100%]" @click="handleBackLogin()" />
  </el-form>
</template>
<script lang="ts" setup>
import { ElLoading, ElMessage, ElMessageBox, FormInstance } from 'element-plus'
import LoginFormTitle from './LoginFormTitle.vue'
import type { RouteLocationNormalizedLoaded } from 'vue-router'
import { useIcon } from '@/hooks/web/useIcon'
import { usePermissionStore } from '@/store/modules/permission'
import * as LoginApi from '@/api/login'
import { LoginStateEnum, useLoginState } from './useLogin'
import {
  CheckEmailExistReq,
  CheckMobileExistReq,
  CheckUserNameExistReq,
  RegisterUserReq
} from '@/models/auth/LoginUserModel'
import { QueryTenantByNameReq } from '@/models/auth/TenantInfoModel'
import cache from '@/utils/cache'
import { CacheKey } from '@/utils/globalConstants'
import Logger from '@/utils/Logger'
import { ClickCaptchaData, ClickCaptchaDot } from '@/components/ClickCaptcha/src/meta/data'
import { ClickCaptchaConf } from '@/components/ClickCaptcha/src/meta/conf'
import { ProcessingStatus } from '@/config/processingStatus'
import { CheckCaptchaReq, CheckPoint } from '@/models/auth/CaptchaModel'
import { useFormValid } from './useLogin'
import { useMessage } from '@/hooks/web/useMessage'

defineOptions({ name: 'RegisterForm' })

const { t } = useI18n()
// 图标
const iconHouse = useIcon({ icon: 'ep:house' })
const iconAvatar = useIcon({ icon: 'ep:avatar' })
const iconLock = useIcon({ icon: 'ep:lock' })
const iconDomain = useIcon({ icon: 'ep:link' })
const iconPhone = useIcon({ icon: 'ep:cellphone' })
const iconEmail = useIcon({ icon: 'ep:message' })
// ###  end icon
const formLogin = ref<FormInstance>()
const { handleBackLogin, getLoginState } = useLoginState()
const { currentRoute, push } = useRouter()
const permissionStore = usePermissionStore()
const redirect = ref<string>('')
const loginLoading = ref(false)
const { validForm } = useFormValid(formLogin)
// 测试

// 验证码处理
const clickCaptchaInstance = ref()
const captchaData = reactive<ClickCaptchaData>({
  image: '',
  thumb: '',
  key: ''
})
const captchaEvents = {
  click(x: number, y: number): void {},
  confirm: async (dots: Array<ClickCaptchaDot>, reset: () => void) => {
    const reqParams = dots.map<CheckPoint>((item) => {
      return {
        X: item.x,
        Y: item.y
      }
    })
    const flag = await checkCaptchaImage(reqParams)
    if (!flag) {
      clickCaptchaInstance.value?.refresh()
      return
    }
    clickCaptchaInstance.value?.close()
  },
  async refresh() {
    await getCaptchaImage()
  },
   async close(): Promise<void> {
    await handleRegister()
  }
}
const captchaConf = reactive<ClickCaptchaConf>({
  width: 400,
  height: 250
})

const getShow = computed(() => unref(getLoginState) === LoginStateEnum.REGISTER)

//  判断两次密码是否一致
const equalToPassword = (_rule, value, callback) => {
  if (registeParam.PassWord !== value) {
    callback(new Error('两次输入的密码不一致'))
    return
  }
  callback()
}
// 账号校验
const checkUsername = (_rule, username, callback) => {
  if (!username) {
    callback(new Error('请输入您的账号'))
    return
  }
  const queryParam: CheckUserNameExistReq = {
    UserName: username
  }
  LoginApi.checkUserName(queryParam)
    .then((res) => {
      if (res.Status !== 0 || !res.Data.Ok) {
        callback(new Error(res.Message))
      }
    })
    .catch(() => {
      callback(new Error('账号校验失败,重新输入'))
    })
}

// 手机号验证
const checkMobile = (_rule, mobile, callback) => {
  if (!mobile) {
    callback(new Error('请输入您的手机号'))
    return
  }
  const checkMobileReq: CheckMobileExistReq = {
    Mobile: mobile
  }
  LoginApi.checkMobile(checkMobileReq)
    .then((res) => {
      if (res.Status !== 0 || !res.Data.Ok) {
        callback(new Error(res.Message))
      }
    })
    .catch(() => callback(new Error('手机号校验失败,重新输入')))
}

// email验证
const checkEmail = (_rule, email, callback) => {
  if (!email) {
    callback(new Error('请输入您的邮箱'))
    return
  }
  const checkEmailReq: CheckEmailExistReq = {
    Email: email
  }
  LoginApi.checkEmail(checkEmailReq)
    .then((res) => {
      if (res.Status !== 0 || !res.Data.Ok) {
        callback(new Error(res.Message))
      }
    })
    .catch(() => callback(new Error('邮箱校验失败,重新输入')))
}

// 检查全名
const checkFullName = (_rule, fullName, callback) => {
  if (!fullName) {
    callback(new Error('请输入您的全名'))
    return
  }
  callback()
}

// 检查租户名称
const checkTenantName = (_rule, tenantName, callback) => {
  if (!tenantName) {
    callback(new Error('请输入您的租户名称'))
    return
  }
  callback()
}

// 注册表单初始化配置参数
const registerInitData = reactive({
  // 是否显示密码
  IsShowPassword: false,
  // 是否开启验证码
  CaptchaEnable: import.meta.env.VITE_APP_CAPTCHA_ENABLE as unknown as boolean,
  // 是否开启租户
  TenantEnable: import.meta.env.VITE_APP_TENANT_ENABLE as unknown as boolean,
  // 验证码类型
  CaptchaVerification: '',
  //是否注册租户
  RegisterTenant: 1,
  // 保存标志
  RememberMe: true,
  // 是否系统管理员
  IsAdmin: false
})

// 注册请求参数
const registeParam = reactive<RegisterUserReq>({
  TenantName: '',
  UserName: '',
  PassWord: '',
  ConfirmPassword: '',
  Mobile: '',
  Email: '',
  FullName: '',
  TenantDomain: ''
})

// 租户必须填写
const requiredTenant = computed(() => registerInitData.RegisterTenant == 1)

// 注册表单验证规则
const registerRules = {
  TenantName: [
    { required: requiredTenant.value, trigger: 'blur', message: '请输入您所属的租户' },
    { min: 2, max: 20, message: '租户账号长度必须介于 2 和 20 之间', trigger: 'blur' }
  ],
  UserName: [
    { required: true, trigger: 'blur', message: '请输入您的账号' },
    { min: 4, max: 30, message: '用户账号长度必须介于 4 和 30 之间', trigger: 'blur' }
  ],
  FullName: [
    { required: true, trigger: 'blur', message: '请输入您的全称' },
    { min: 0, max: 30, message: '全称长度必须介于 0 和 30 之间', trigger: 'blur' },
    { required: true, validator: checkFullName, trigger: 'blur' }
  ],
  PassWord: [
    { required: true, trigger: 'blur', message: '请输入您的密码' },
    { min: 5, max: 20, message: '用户密码长度必须介于 5 和 20 之间', trigger: 'blur' },
    { pattern: /^[^<>"'|\\]+$/, message: '不能包含非法字符：< > " \' \\\ |', trigger: 'blur' }
  ],
  ConfirmPassword: [
    { required: true, trigger: 'blur', message: '请再次输入您的密码' },
    { required: true, validator: equalToPassword, trigger: 'blur' }
  ],
  TenantDomain: [
    { required: requiredTenant.value, trigger: 'blur', message: '请输入您网站地址' },
    { min: 5, max: 250, message: '域名长度必须介于 5 和 250 之间', trigger: 'blur' },
    {
      pattern:
        /^(?=^.{5,100}$)((http|https):\/\/)?(www\.)?[a-zA-Z0-9]+\.[a-zA-Z0-9]+(\.[a-zA-Z0-9]+)*(\/[a-zA-Z0-9]+\/?)*$/,
      message: '请输入正确的网站地址',
      trigger: 'blur'
    }
  ],
  Mobile: [
    { required: true, trigger: 'blur', message: '请输入您的手机号码' },
    { min: 11, max: 11, message: '手机号码长度必须为11位', trigger: 'blur' },
    { pattern: /^[1][3,4,5,6,7,8,9][0-9]{9}$/, message: '请输入正确的手机号码', trigger: 'blur' },
  ],
  Email: [
    { required: true, trigger: 'blur', message: '请输入您的邮箱' },
    { min: 5, max: 50, message: '邮箱长度必须介于 5 和 50 之间', trigger: 'blur' },
    {
      pattern: /^[A-Za-z0-9\u4e00-\u9fa5]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/,
      message: '请输入正确邮箱地址',
      trigger: 'blur'
    }
  ]
}

// 提交注册
const handleRegister = async () => {
  loading.value = true
  try {
    const res = await LoginApi.register(registeParam)
    if (!res || res.Status !== 0 || !res.Data.Ok) {
      ElMessage.warning(res.Message)
      return
    }
    loading.value = ElLoading.service({
      lock: true,
      text: '正在加载系统中...',
      background: 'rgba(0, 0, 0, 0.7)'
    })

    // 清除登录表单
    ElMessage.success({
      message: '注册成功，请登录',
      duration: 2000,
      onClose: () => {
        formLogin.value?.resetFields()
        registerInitData.RememberMe = true
      }
    })

    cache.clearLoginForm()

    if (!redirect.value) {
      redirect.value = '/'
    }
    // 判断是否为SSO登录
    if (redirect.value.indexOf('sso') !== -1) {
      window.location.href = window.location.href.replace('/login?redirect=', '')
    } else {
      push({ path: redirect.value || permissionStore.addRouters[0].path })
    }
  } finally {
    loginLoading.value = false
    loading.value.close && loading.value.close()
  }
}

// 获取验证码图片
const getCaptchaImage = async () => {
  const resp = await LoginApi.getCode({ ClickCaptchaType: 1 })
  if (!resp || resp.Status !== ProcessingStatus.ProcessingSuccess || !resp.Data.Ok) {
    ElMessage.warning(resp.Message)
    return
  }
  captchaData.key = resp.Data.CaptchaKey
  captchaData.image = resp.Data.CaptchaImage as unknown as string
  captchaData.thumb = resp.Data.CaptchCheckBase64Image as unknown as string
}

// 校检码是否正确
const checkCaptchaImage = async (checkPoints: Array<CheckPoint>): Promise<boolean> => {
  const reqParams: CheckCaptchaReq = {
    CaptchaKey: captchaData.key,
    CaptchaDots: checkPoints
  }
  const res = await LoginApi.reqCheck(reqParams)
  if (!res || !res.Data || res.Status !== ProcessingStatus.ProcessingSuccess) {
    ElMessage.warning(res.Message)
    return false
  }
  return res.Data.Ok
}

// 获取验证码
const getCode = async () => {
  const flag = await validForm()
  if (!flag) {
    return
  }
  clickCaptchaInstance.value.show && clickCaptchaInstance.value.show()
  await getCaptchaImage()
}

// 获取租户 ID
const getTenantId = async () => {
  if (registerInitData.TenantEnable) {
    const reqParams: QueryTenantByNameReq = {
      Name: registeParam.TenantName as unknown as string
    }
    const res = await LoginApi.getTenantIdByName(reqParams)
    if (!res || res.Status !== 0) {
      ElMessageBox.alert(res.Message, '提示').then(() => {
        // 刷新页面
        location.reload()
      })
      return
    }
    cache.writeCache(res.Data.Id, CacheKey.TenantId)
  }
}

// 根据域名，获得租户信息
const getTenantByWebsite = async () => {
  try {
    const website = location.host
    const res = await LoginApi.getTenantByWebsite(website)
    if (!res || res.Status !== 0) {
      ElMessage.warning(res.Message)
      return
    }
    registeParam.TenantName = res.Data.Name
    cache.writeCache(res.Data.Id as unknown as string, CacheKey.TenantId)
  } catch (err) {
    Logger.prettyError('【注册界面】getTenantByWebsite请求异常', err)
  }
}
// ElLoading.service 返回的实例
const loading = ref()

watch(
  () => currentRoute.value,
  (route: RouteLocationNormalizedLoaded) => {
    redirect.value = route?.query?.redirect as string
  },
  {
    immediate: true
  }
)
onMounted(() => {
  getTenantByWebsite()
})
</script>

<style lang="scss" scoped>
:deep(.anticon) {
  &:hover {
    color: var(--el-color-primary) !important;
  }
}

.login-code {
  float: right;
  width: 100%;
  height: 38px;

  img {
    width: 100%;
    height: auto;
    max-width: 100px;
    vertical-align: middle;
    cursor: pointer;
  }
}
</style>
